<?php

/**
 * Controller is the customized base controller class.
 * All controller classes for this application should extend from this base class.
 */
class Controller extends CController
{

    /**
     * @var string the default layout for the controller view. Defaults to '//layouts/column1',
     * meaning using a single column layout. See 'protected/views/layouts/column1.php'.
     */
    public $layout = '//layouts/column1';

    /**
     * @var array context menu items. This property will be assigned to {@link CMenu::items}.
     */
    public $menu = array();

    /**
     * @var array the breadcrumbs of the current page. The value of this property will
     * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links}
     * for more details on how to specify this property.
     */
    public $breadcrumbs = array();
    
    /**
     * Registra a hierarquia de perfis, guardando o perfil e seus filhos
     *
     * @var array 
     */
    private $perfis_filhos = array();

    /**
     * @return array action filters
     */
    public function filters()
    {
        return array(
            'accessControl', // perform access control for CRUD operations
            'postOnly + delete', // we only allow deletion via POST request
        );
    }

    /**
     * Especifica as regras de acesso
     * This method is used by the 'accessControl' filter.
     * @return array Retorna o controle de acesso
     */
    public function accessRules()
    {
        return array(
            array('allow',
                'expression' => 'Yii::app()->controller->hasPermissao()'
            ),
            array('deny')
        );
    }
    
    private function getRegrasAcesso($perfil_logado = null) {
        $regras = false; //Yii::app()->cache->get('regras_acesso');
        
        if ($regras === false) {
            $regras = array();
            $database = Yii::app()->db;
            
            $perfis_result     = $database->createCommand()->select('*')->from('perfil')->queryAll();
            $recursos_result   = $database->createCommand()->select('*')->from('recurso')->queryAll();
            $permissoes_result = $database->createCommand()->select('*')->from('permissao')->queryAll();
            
            // Organiza os perfis para facilitar na busca por indice
            $perfis = array();
            foreach($perfis_result as $perfil) {
                $perfis[$perfil['id']] = $perfil['nome'];
                $this->perfis_filhos[$perfil['pai_id']][$perfil['id']] = $perfil['nome'];
            }
            
            // Organiza os recursos para facilitar na busca por indice
            $recursos = array();
            foreach($recursos_result as $recurso)
                $recursos[$recurso['id']] = $recurso['nome'];
            
            // Varre as permissões, realizando a associação entre perfil e 
            // permissão
            foreach($permissoes_result as $permissao) {
                $recurso = $recursos[$permissao['recurso_id']];
                
                // Adiciona o recurso ao perfil
                $regras[$perfis[$permissao['perfil_id']]][$recurso] = true;
                
                // Verifica se tem filho
                if (isset($this->perfis_filhos[$permissao['perfil_id']])) {
                    // Obtem os filhos recursivamente
                    $filhos = $this->getPerfilFilhos($permissao['perfil_id']);
                    
                    // Adiciona nos filhos a permissão
                    foreach($filhos as $perfil_nome) {
                        $regras[$perfil_nome][$recurso] = true;
                    }
                }
            }
            
            Yii::app()->cache->set('regras_acesso', $regras, 0);
        }
        
        return $perfil_logado ? $regras[$perfil_logado] : $regras;
    }
    
    /**
     * Verifica se o usuário logado tem permissão para acessar uma determinada pagina
     * 
     * @return boolean
     */
    protected function hasPermissao() {
        $controller = str_replace('/', '.', strtolower(Yii::app()->controller->id));
        $action     = strtolower(Yii::app()->controller->action->id);
        
        // Se for um visitante, obtem as permissões de visitante
        if (Yii::app()->user->isGuest) {
            $recursos = $this->getRegrasAcesso('visitante');
        }
        // Se for um usuário logado
        else {
            $usuario = Usuario::model()->findByPk(Yii::app()->user->id);
            $recursos = $this->getRegrasAcesso($usuario->perfil->nome);
        }
        
        return isset($recursos["{$controller}.*"]) || isset($recursos["{$controller}.{$action}"]);
    }
    
    private function getPerfilFilhos($perfil_id) {
        $filhos = array();
        
        foreach($this->perfis_filhos[$perfil_id] as $id => $perfil) {
            $filhos[$id] = $perfil;
            
            // Verfica se o perfil atual tem filhos
            if (isset($this->perfis_filhos[$id])) {
                $filhos += $this->getPerfilFilhos($id);
            }
        }
        
        return $filhos;
    }
}
